﻿/**************************************************************
 *
 * 唯一标识：be28a09b-52d3-4202-9f45-c4fc25eb41ab
 * 命名空间：Sgr.UPMS.Controllers
 * 创建时间：2023/8/27 20:32:39
 * 机器名称：DESKTOP-S0D075D
 * 创建者：antho
 * 电子邮箱：fengqinhua2016@163.com
 * 描述：
 *
 **************************************************************/

using MediatR;
using Microsoft.AspNetCore.Mvc;
using Sgr.AspNetCore.ActionFilters.AuditLogs;
using Sgr.AspNetCore.ActionFilters.Permissions;
using Sgr.Caching.Services;
using Sgr.UPMS.Application.Commands.Menus;
using Sgr.UPMS.Application.Queries;
using Sgr.UPMS.Application.ViewModels;

namespace Sgr.UPMS.Controllers
{
    /// <summary>
    /// 菜单管理接口
    /// </summary>
    [Route("api/v1/sgr/menus")]
    [ApiController]
    [Produces("application/json")]
    [Tags("Menu")]
    public class MenuController : ControllerBase
    {
        private readonly IMediator _mediator;
        private readonly IMenuQueries _menuQueries;

        /// <summary>
        /// 初始化菜单管理控制器
        /// </summary>
        public MenuController(IMediator mediator,
            IMenuQueries menuQueries)
        {
            _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
            _menuQueries = menuQueries ?? throw new ArgumentNullException(nameof(menuQueries));
        }

        #region Command

        /// <summary>
        /// 创建菜单
        /// </summary>
        /// <param name="command">创建菜单的请求参数</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <remarks>
        /// 示例请求:
        ///
        ///     POST /api/v1/sgr/menus
        ///     {
        ///         "name": "系统管理",
        ///         "type": "Directory",
        ///         "parentId": null,
        ///         "icon": "setting",
        ///         "routeName": "system",
        ///         "routePath": "/system",
        ///         "componentPath": "Layout",
        ///         "permission": "system",
        ///         "order": 1,
        ///         "hidden": false,
        ///         "keepAlive": true,
        ///         "affix": false
        ///     }
        /// </remarks>
        /// <response code="200">创建成功</response>
        /// <response code="400">请求参数验证失败</response>
        /// <response code="401">未经授权的访问</response>
        [CheckPermission(Permissions.CreateMenu)]
        [HttpPost]
        [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
        [AuditLogActionFilter("创建菜单")]
        public async Task<ActionResult<bool>> CreateAsync([FromBody] CreateMenuCommand command, CancellationToken cancellationToken)
        {
            var result = await _mediator.Send(command, cancellationToken);
            return !result.IsSuccess ? this.CustomBadRequest(result.Message) : Ok(result.Data);
        }

        /// <summary>
        /// 更新菜单信息
        /// </summary>
        /// <param name="command">更新菜单的请求参数</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <remarks>
        /// 示例请求:
        ///
        ///     PUT /api/v1/sgr/menus
        ///     {
        ///         "id": 1,
        ///         "name": "系统管理",
        ///         "parentId": null,
        ///         "icon": "setting",
        ///         "routeName": "system",
        ///         "routePath": "/system",
        ///         "componentPath": "Layout",
        ///         "permission": "system",
        ///         "order": 1,
        ///         "hidden": false,
        ///         "keepAlive": true,
        ///         "isActive": true
        ///     }
        /// </remarks>
        /// <response code="200">更新成功</response>
        /// <response code="400">请求参数验证失败</response>
        /// <response code="401">未经授权的访问</response>
        [CheckPermission(Permissions.UpdateMenu)]
        [HttpPut]
        [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
        [AuditLogActionFilter("修改菜单")]
        public async Task<ActionResult<bool>> UpdateAsync([FromBody] UpdateMenuCommand command, CancellationToken cancellationToken)
        {
            var result = await _mediator.Send(command, cancellationToken);
            return !result.IsSuccess ? this.CustomBadRequest(result.Message) : Ok(result.Data);
        }

        /// <summary>
        /// 删除菜单
        /// </summary>
        /// <param name="id">菜单ID</param>
        /// <param name="cascade">是否级联删除子菜单，默认为true</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <response code="200">删除成功</response>
        /// <response code="400">请求参数验证失败</response>
        /// <response code="401">未经授权的访问</response>
        [CheckPermission(Permissions.DeleteMenu)]
        [HttpDelete("{id:long:min(1)}")]
        [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
        [AuditLogActionFilter("删除菜单")]
        public async Task<ActionResult<bool>> DeleteAsync(
            [FromRoute] long id,
            [FromQuery] bool? cascade = true,
            CancellationToken cancellationToken = default)
        {
            var result = await _mediator.Send(new DeleteMenuCommand { Id = id, Cascade = cascade ?? true }, cancellationToken);
            return !result.IsSuccess ? this.CustomBadRequest(result.Message) : Ok(result.Data);
        }

        /// <summary>
        /// 刷新菜单缓存
        /// </summary>
        /// <param name="cacheManager">缓存管理器</param>
        /// <param name="cancellationToken">取消操作的标记</param>
        /// <returns>操作结果</returns>
        [CheckPermission(Permissions.CreateMenu)]
        [HttpPost("refresh")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [AuditLogActionFilter("刷新菜单缓存")]
        public async Task<IActionResult> RefreshAsync(ICacheManager cacheManager, CancellationToken cancellationToken = default)
        {
            await cacheManager.RemoveAsync(CacheKeys.GetAllMenusKey(), cancellationToken);

            return NoContent();
        }

        #endregion Command

        #region Queries

        /// <summary>
        /// 获取菜单详情
        /// </summary>
        /// <param name="id">菜单ID</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <response code="200">获取成功</response>
        /// <response code="401">未经授权的访问</response>
        /// <response code="404">指定的菜单不存在</response>
        [CheckPermission(Permissions.ViewMenu)]
        [HttpGet("{id:long:min(1)}")]
        [ProducesResponseType(typeof(OutMenuViewModel), StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status404NotFound)]
        [AuditLogActionFilter("获取菜单详情")]
        public async Task<ActionResult<OutMenuViewModel>> GetByIdAsync([FromRoute] long id, CancellationToken cancellationToken)
        {
            var result = await _menuQueries.GetByIdAsync(id, cancellationToken);
            return result == null ? NotFound() : Ok(result);
        }

        /// <summary>
        /// 查询菜单列表
        /// </summary>
        /// <param name="request">查询条件</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <remarks>
        /// 示例请求:
        ///
        ///     POST /api/v1/sgr/menus/search
        ///     {
        ///         "name": "系统",
        ///         "type": "Directory"
        ///     }
        /// </remarks>
        /// <response code="200">查询成功</response>
        /// <response code="401">未经授权的访问</response>
        [CheckPermission(Permissions.ViewMenu)]
        [HttpPost("search")]
        [ProducesResponseType(typeof(IEnumerable<OutMenuViewModel>), StatusCodes.Status200OK)]
        [AuditLogActionFilter("查询菜单列表")]
        public async Task<ActionResult<IEnumerable<OutMenuViewModel>>> SearchAsync([FromBody] InMenuSearchModel request, CancellationToken cancellationToken)
        {
            return Ok(await _menuQueries.GetListAsync(request, cancellationToken));
        }

        #endregion Queries
    }
}